    .data
NewLine:        .asciiz "\n"
RegisterIs:     .asciiz "Register is: "

#--------
# $a0   =>  pointer to first position of 'subcube'
# $a1   =>  length of an edge of the 'subcube'
# $a2   =>  number of dimensions
# $a3   =>  length of an edge of the original cube
#
# $v0   =>  range
# $v1   =>  floor of average
#--------

    .text

CubeStats:

    # Move stack pointer down to save $fp
    addi            $sp, $sp, -4
    sw              $fp, 0($sp)

    # Adjust frame pointer for this function's frame
    move            $fp, $sp

    # Store argument registers, return address and S registers
    sw              $a0, -4($fp)
    sw              $a1, -8($fp)
    sw              $a2, -12($fp)
    sw              $a3, -16($fp)

    sw              $ra, -20($fp)

    sw              $s0, -24($fp)
    sw              $s1, -28($fp)
    sw              $s2, -32($fp)
    sw              $s3, -36($fp)
    sw              $s4, -40($fp)
    sw              $s5, -44($fp)
    sw              $s6, -48($fp)
    sw              $s7, -52($fp)

    # Copy first, edgeLength and dimension to S registers
    move            $s5, $a0
    move            $s6, $a1
    move            $s7, $a2

    # Move $sp to last frame position tentatively
    addiu           $sp, $sp, -52


# * + * + * + * + * + * + * + * + * + * + * + * + * #
#   int ArrayOfCs[dimension];
# * + * + * + * + * + * + * + * + * + * + * + * + * #

    # Allocate space for an integer array of size dimension
    # by multiplying the dimensions times 4, converting to negative
    # and adding the result to the stack pointer.
    mul             $t0, $a2, 4
    nor             $t0, $t0, $0
    addiu           $t0, $t0, 1
    add             $sp, $sp, $t0

    # Save this position to a register since it will represent
    # the local array from the C program.
    move            $s0, $sp


# * + * + * + * + * + * + * + * + * + * + * + * + * #
#   int index;
#   for (index = 0; index < dimension; ++index) {
#       ArrayOfCs[index] = 0;  }
# * + * + * + * + * + * + * + * + * + * + * + * + * #

# Now we initialize the array by zeroing it out with a loop.
Initialize_ArrayOfCs:
    move            $t0, $0

    addiu           $t2, $0, 4
    mul             $t3, $s7, $t2
    
Initialize_ArrayOfCs_LOOP:
    bge             $t0, $t3, Exit_Initialize_ArrayOfCs     # (index >= dimension) exit loop
    
#$%addi    $v0, $0, 1
#$%addiu   $a0, $t0, 0
#$%syscall
#$%addi    $v0, $0, 4
#$%la      $a0, NewLine
#$%syscall

    addu            $t1, $t0, $s0
    sw              $0, 0($t1)
    addiu           $t0, $t0, 4
    j               Initialize_ArrayOfCs_LOOP

Exit_Initialize_ArrayOfCs:

# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
#   for (i = 0; i < power(edgeLength, dimension-1); ++i) {
# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
FOR_i:
    move            $t0, $0

    move            $a0, $s6
    addiu           $a1, $s7, -1
    jal             power

FOR_i_LOOP:
    bge             $t0, $s7, Exit_FOR_i

# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
#   for (j = 0; j < edgeLength; ++j) {
# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
FOR_j:
    move            $t1, $0

FOR_j_LOOP:
    bge             $t1, $s6, Exit_FOR_j    # (j >= edgeLength) exit loop

    sw              $t1, 0($s0)             # ArrayOfCs[0] := j

# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
#   for (k = 0; k < dimension; ++k) {
#       polynomial += ArrayOfCs[k] * power(bArraySize, k);  }
# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
FOR_k:
    move            $t2, $0                 # k = 0
    move            $t3, $0                 # $t3 := sum of terms of the polynomial

    addiu           $t5, $0, 4
    mul             $t4, $s7, $t5           # $t4 := dimension * 4
    
FOR_k_LOOP:
    bge             $t2, $t4, Exit_FOR_k

    addu            $t5, $s0, $t2           # &ArrayOfCs[k]
    lw              $t5, 0($t5)             # $t5 := ArrayOfCs[k]

    lw              $a0, -16($fp)           # $a0 := bArraySize
    move            $a1, $t2                # $a1 := k
    jal             power

    mul             $t5, $t5, $v0           # $t5 := ArrayOfCs[k] * power(bArraySize, k)
    addu            $t3, $t3, $t5           # $t3 += $t5 = a term of the polynomial

    addiu           $t2, $t2, 4
    j               FOR_k_LOOP

Exit_FOR_k:
    addiu           $t5, $0, 4
    mul             $t3, $t3, $t5           # Adjust the sum for in bytes
    addu            $t3, $s5, $t3           # $t3 := first + proper offset for the next element

# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
#   if (*polynomial < min) {
#       min = *polynomial;  }
#   else if (*polynomial > max) {
#       max = *polynomial;  }
#   total += *polynomial;
# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
    lw              $t4, 0($t3)             # $t4 := *polynomial

addiu   $v0, $0, 1
move    $a0, $t4
syscall
addiu   $v0, $0, 4
la      $a0, NewLine
syscall

    la              $t5, min
    lw              $t6, 0($t5)             # $t6 := min
    bge             $t4, $t6, Polynomial_NotLessThan_Min
    sw              $t4, 0($t5)
    j               Polynomial_NotGreaterThan_Max
Polynomial_NotLessThan_Min:
    la              $t5, max
    lw              $t6, 0($t5)             # $t6 := max
    ble             $t4, $t6, Polynomial_NotGreaterThan_Max
    sw              $t4, 0($t5)
Polynomial_NotGreaterThan_Max:
    la              $t5, total
    lw              $t6, 0($t5)             # $t6 := total
    addu            $t6, $t6, $t4           # total += *polynomial

    addiu           $t1, $t1, 1             # ++j
    j               FOR_j_LOOP


Exit_FOR_j:

# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
#   q = 1;
#   while (ArrayOfCs[q] == edgeLength-1) {
#       ArrayOfCs[q] = 0;
#       ++q;  }
# * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * #
WHILE_Increment_Coefficients:
    addiu           $t1, $0, 4              # q = 1
    addiu           $t2, $s6, -1            # edgeLength-1

WHILE_Increment_Coefficients_LOOP:
    addu            $t3, $s0, $t1           # &ArrayOfCs[q]
    lw              $t4, 0($t3)             # $t4 := ArrayOfCs[q]
    bne             $t4, $t2, Exit_WHILE_Increment_Coefficients     # (ArrayOfCs[q] >= edgeLength-1) exit loop

    sw              $0, 0($t3)              # ArrayOfCs[q] := 0
    addiu           $t1, $t1, 4             # ++q
    j               WHILE_Increment_Coefficients_LOOP

Exit_WHILE_Increment_Coefficients:
    addiu           $t4, $t4, 1
    sw              $t4, 0($t3)

    # ++i and loop back
    addiu           $t0, $t0, 1
    j               FOR_i_LOOP

Exit_FOR_i:
    la              $t0, min
    la              $t1, max
    la              $t2, total

    lw              $t0, 0($t0)             # $t0 := min
    lw              $t1, 0($t1)             # $t1 := max
    subu            $t0, $t1, $t0           # $t0 := Range = max - min

    lw              $t2, 0($t2)             # $t2 := total
    move            $a0, $s6                # $a0 := edgeLength
    move            $a1, $s7                # $a1 := dimension
    jal             power
    div             $t2, $v0                # total / power(edgeLength, dimension)

    move            $v0, $t0                # $v0 := Range
    mflo            $v1                     # $v1 := truncated average

CubeStats_Done:
    # Restore registers
    lw              $a0, -4($fp)
    lw              $a1, -8($fp)
    lw              $a2, -12($fp)
    lw              $a3, -16($fp)

    lw              $ra, -20($fp)

    lw              $s0, -24($fp)
    lw              $s1, -28($fp)
    lw              $s2, -32($fp)
    lw              $s3, -36($fp)
    lw              $s4, -40($fp)
    lw              $s5, -44($fp)
    lw              $s6, -48($fp)
    lw              $s7, -52($fp)

    # Restore frame pointer, and stack pointer
    move            $sp, $fp
    lw              $fp, 0($sp)
    addiu           $sp, $sp, 4

    jr              $ra

    
        
    
